/******************************************************************************
 ** File Name:      i2c_drv.c                                                 *
 ** Author:         Richard Yang                                              *
 ** DATE:           01/16/2001                                                *
 ** Copyright:      2002 Spreatrum, Incoporated. All Rights Reserved.         *
 ** Description:    This file defines the basic operation interfaces of       *
 **                 serrial device. It manages create, send, receive          *
 **                 interface of serrial port.                                *
 ******************************************************************************

 ******************************************************************************
 **                        Edit History                                       *
 ** ------------------------------------------------------------------------- *
 ** DATE           NAME             DESCRIPTION                               *
 ** 01/16/2001     Richard.Yang     Create.                                   *
 ** 04/02/2002     Lin.Liu            Code                                      *
 ** 04/22/2002     Lin.liu          Set CPC_ZD_WPU after change clock.        *
 ** 04/23/2002     Lin.liu          1. Remove i2c_clk to i2c_drv.h            * 
 **                                 2. Remove i2c_inited flag                 *
 ******************************************************************************/

/**---------------------------------------------------------------------------*
 **                         Dependencies                                      *
 **---------------------------------------------------------------------------*/
#include "tb_drv.h"
#include "sc_reg.h"
#include "chip.h"
#include "i2c_drv.h"
#include "os_api.h"

/**---------------------------------------------------------------------------*
 **                         Debugging Flag                                    *
 **---------------------------------------------------------------------------*/
/**---------------------------------------------------------------------------*
 **                         Compiler Flag                                     *
 **---------------------------------------------------------------------------*/
#ifdef   __cplusplus
    extern   "C" 
    {
#endif

/**---------------------------------------------------------------------------*
 **                            Macro Define
 **---------------------------------------------------------------------------*/

#define I2C_TIMEOUT_FACTOR  500000  //the critical value is 10000


#define I2C_READ_BIT        0x1

//#define I2C_USE_INT

#ifndef I2C_USE_INT 

#define I2C_WAIT_INT                                                  \
{                                                                     \
    timetick = SYSTEM_CURRENT_CLOCK;                                  \
    while(!(ptr->ctl & I2CCTL_INT))                                   \
    {                                                                 \
        uint32 wait_counter=0x00;   \
        for(wait_counter=0x00; wait_counter<0xff;wait_counter++)    \
        {                                                   \
            wait_counter++;                         \
        }                                                    \
        if((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)        \
        {                                                             \
            if(ERR_I2C_NONE == ret_value)                             \
            {                                                         \
                ret_value = ERR_I2C_INT_TIMEOUT;                      \
            }                                                         \
            break;                                                    \
        }                                                             \
                                                                      \
    }                                                                 \
                                                                      \
}

#else

#define I2C_WAIT_INT                                                  \
{                                                                     \
    timetick = SYSTEM_CURRENT_CLOCK;                                  \
    while (g_wait_i2c_int_flag)                                       \
    {                                                                 \
        if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \
        {                                                             \
            if(ERR_I2C_NONE == ret_value)                             \
            {                                                         \
                ret_value = ERR_I2C_INT_TIMEOUT;                      \
            }                                                         \
            break;                                                    \
        }                                                             \
    }                                                                 \
    g_wait_i2c_int_flag = 1;                                          \
}

#endif 
       
#define I2C_WAIT_BUSY                                                 \
{                                                                     \
    timetick = SYSTEM_CURRENT_CLOCK;                                  \
    while(ptr->cmd & I2CCMD_BUS)                                      \
    {                                                                 \
        if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \
        {                                                             \
            if(ERR_I2C_NONE == ret_value)                             \
            {                                                         \
                ret_value = ERR_I2C_BUSY_TIMEOUT;                     \
            }                                                         \
            break;                                                    \
        }                                                             \
    }                                                                 \
                                                                      \
}
       
#define I2C_WAIT_ACK                                                  \
{                                                                     \
    timetick = SYSTEM_CURRENT_CLOCK;                                  \
    while(ptr->cmd & I2CCMD_ACK)                                      \
    {                                                                 \
        if ((SYSTEM_CURRENT_CLOCK - timetick) >= g_i2c_timeout)       \
        {                                                             \
            if(ERR_I2C_NONE == ret_value)                             \
            {                                                         \
                ret_value = ERR_I2C_ACK_TIMEOUT;                      \
            }                                                         \
            break;                                                    \
        }                                                             \
    }                                                                 \
}

#ifndef I2C_USE_INT

#define I2C_CLEAR_INT                                                 \
{                                                                     \
    I2C_WAIT_BUSY                                                     \
    TB_REG_OR(I2C_CMD, I2CCMD_INT_ACK);                               \
}

#else

#define I2C_CLEAR_INT  

#endif

#define I2C_GetMutex(mutex)  {\
	uint32 ret = SCI_SUCCESS;\
	if( NULL == mutex )\
	{\
		return ERR_I2C_NO_MUTEX;\
	}\
	if(SCI_InThreadContext())\
	{\
		ret = SCI_GetMutex(mutex, SCI_WAIT_FOREVER);\
	}\
	SCI_ASSERT( ret == SCI_SUCCESS );\
}

#define I2C_PutMutex(mutex)  {\
	uint32 ret = SCI_SUCCESS;\
	if( NULL == mutex )\
	{\
		return ERR_I2C_NO_MUTEX;\
	}\
	if(SCI_InThreadContext())\
	{\
		ret = SCI_PutMutex( mutex );\
	}\
	SCI_ASSERT( ret == SCI_SUCCESS );\
}


/**---------------------------------------------------------------------------*
 **                            Local Variables
 **---------------------------------------------------------------------------*/
LOCAL SCI_MUTEX_PTR	s_i2c_mutex_ptr = SCI_NULL;

/**---------------------------------------------------------------------------*
 **                            Global Variables
 **---------------------------------------------------------------------------*/
volatile BOOLEAN    g_wait_i2c_int_flag;
volatile BOOLEAN    g_i2c_open_flag=FALSE;
volatile uint32     g_i2c_timeout = 2; //unit is ms

/**---------------------------------------------------------------------------*
 **                      Function  Definitions
 **---------------------------------------------------------------------------*/
/*****************************************************************************/
//  Description: Create Mutex
//	Global resource dependence:
//  Author: hanjun.liu
//	Note:
//		input:
//			none
//		output:
//			none
//		return:
//			Mutex
/*****************************************************************************/
LOCAL SCI_MUTEX_PTR I2C_CreateMutex(void)
{	
	SCI_MUTEX_PTR	mutex = SCI_NULL;
	mutex = SCI_CreateMutex("I2C SYNC MUTEX", SCI_INHERIT);
	SCI_PASSERT((mutex!=NULL),("I2C Great MUTEX fail!"));	
	
	return mutex;	
}//end of IMG_CreateMutex

/*********************************************************************/
//  Description: i2c interrupt service 
//  Input:
//      param         not use
//  Return:
//      None
//    Note: 
//      None       
/*********************************************************************/
PUBLIC void I2C_Handler(uint32 param)
{
    param = param; // avoid compiler warning

    /* set i2c flag  */    
    g_wait_i2c_int_flag = FALSE;
    
    while((*(volatile uint32*)(I2C_CMD)) & I2CCMD_BUS);
    
    /* clear i2c int  */
    TB_REG_OR(I2C_CMD, I2CCMD_INT_ACK);    
}
/*********************************************************************/
//  Description: i2c init fuction 
//  Input:
//      freq     I2C SCL's frequency
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_Init(uint32 freq)
{    
    volatile I2C_CTL_REG_T *ptr = (I2C_CTL_REG_T *)I2C_BASE;

    SCI_ASSERT (freq > 0);

    g_wait_i2c_int_flag = TRUE;
    g_i2c_open_flag=TRUE;

    // gen0, enable i2c device.
    TB_REG_OR(GR_GEN0, GEN0_I2C);    
    

    ptr->rst = BIT_0;//why reset
    ptr->ctl &= ~(I2CCTL_EN);//you must first disable i2c module then change clock  
    ptr->ctl &= ~(I2CCTL_IE);
    ptr->ctl &= ~(I2CCTL_CMDBUF_EN);

    I2C_SetSCLclk(freq);

    TB_REG_OR(I2C_CTL, (I2CCTL_IE | I2CCTL_EN));

     //Clear I2C int
    TB_REG_OR(I2C_CMD, I2CCMD_INT_ACK); 
   
    #ifdef I2C_USE_INT
        DRV_RegHandler( TB_I2C_INT, I2C_Handler);
        TB_EnableINT( TB_I2C_INT );//no need interrupt removed by younger
    #endif
    if(NULL == s_i2c_mutex_ptr)
    {
        s_i2c_mutex_ptr = I2C_CreateMutex();
        SCI_PASSERT(s_i2c_mutex_ptr, ("I2C_DRV: Create Mutex is fail"));
    } 

    return ERR_I2C_NONE;
}
/*********************************************************************/
//  Description: i2c set SCL clock
//  Input:
//      freq     I2C SCL's frequency to be set
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_SetSCLclk(uint32 freq)
{
    uint32 APB_clk,i2c_dvd;
    
    volatile I2C_CTL_REG_T *ptr = (I2C_CTL_REG_T *)I2C_BASE;

    SCI_ASSERT(freq > 0);
    SCI_ASSERT(g_i2c_open_flag);

    APB_clk= CHIP_GetAPBClk();
    i2c_dvd=APB_clk/(4*freq)-1;

    ptr->div0=(uint16)(i2c_dvd & 0xffff);
    ptr->div1=(uint16)(i2c_dvd>>16);

    g_i2c_timeout = I2C_TIMEOUT_FACTOR / (freq);
    
    if(g_i2c_timeout < 2)
        g_i2c_timeout = 2;
    //g_i2c_timeout will be changed according I2C frequency
    
    return ERR_I2C_NONE;
     
      
}
/*********************************************************************/
//  Description: get i2c SCL clock
//  Input:
//      None
//  Return:
//      the freq of i2c SCL clock
//    Note: 
//      None       
/*********************************************************************/
PUBLIC uint32 I2C_GetSCLclk()
{
    uint32 APB_clk,i2c_dvd,freq;
    
    volatile I2C_CTL_REG_T *ptr = (I2C_CTL_REG_T *)I2C_BASE;

    SCI_ASSERT(g_i2c_open_flag);

    APB_clk= CHIP_GetAPBClk();

    i2c_dvd=((ptr->div1)<<16)|(ptr->div0);

    freq=APB_clk/(4*(i2c_dvd+1));


    return freq;

}
/*********************************************************************/
//  Description: Write a command to a slave device
//  Input:
//      addr     the slave device's address
//      command  the command to be set into the slave device's address
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_WriteCmd(uint8 addr,uint8 command, BOOLEAN ack_en)
{
    volatile uint32 timetick = 0; 
    volatile uint32 cmd = 0;
    volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
    uint32   ret_value = ERR_I2C_NONE;
    
    SCI_ASSERT(g_i2c_open_flag);
    SCI_ASSERT(g_i2c_timeout > 0);

    I2C_GetMutex(s_i2c_mutex_ptr);	
    cmd = ((uint32)addr)<<8;
    cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
    ptr->cmd = cmd; 

    I2C_WAIT_INT
    
    I2C_CLEAR_INT
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    cmd = ((uint32)command)<<8;
    cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command
    ptr->cmd = cmd; 

    I2C_WAIT_INT
       
    I2C_CLEAR_INT  

    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }
    I2C_PutMutex(s_i2c_mutex_ptr);

    return ERR_I2C_NONE;
            
}
/*********************************************************************/
//  Description: read a command from the slave device
//  Input:
//      addr     the slave device's address
//      pCmd     the command's pointer
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_ReadCmd(uint8 addr,uint8 *pCmd, BOOLEAN ack_en)
{
    volatile uint32 timetick = 0; 
    volatile uint32 cmd = 0;
    volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
    uint32   ret_value = ERR_I2C_NONE;
    
    SCI_ASSERT(NULL != pCmd);
    SCI_ASSERT(g_i2c_open_flag);
    SCI_ASSERT(g_i2c_timeout > 0);

     I2C_GetMutex(s_i2c_mutex_ptr);	
    cmd = ((uint32)(addr|I2C_READ_BIT))<<8;
    cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
    ptr->cmd = cmd; 

    I2C_WAIT_INT
           
    I2C_CLEAR_INT  

    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    cmd = I2CCMD_READ | I2CCMD_STOP | I2CCMD_TX_ACK;
    ptr->cmd = cmd;
     
    I2C_WAIT_INT
       
    I2C_CLEAR_INT  


    *pCmd=(uint8)((ptr->cmd)>>8);
	
     I2C_PutMutex(s_i2c_mutex_ptr);

    return ERR_I2C_NONE;
}
/*********************************************************************/
//  Description: Write the command array into the slave device 
//  Input:
//      addr     the slave device's address
//      pCmd     the command array's pointer
//      len      the length of the command array
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_WriteCmdArr(uint8 addr, uint8 *pCmd, uint32 len, BOOLEAN ack_en)
{
    volatile uint32 timetick = 0; 
    volatile uint32 i = 0;
    volatile uint32 cmd = 0;
    volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
    uint32   ret_value = ERR_I2C_NONE;
    
    SCI_ASSERT(NULL != pCmd);
    SCI_ASSERT(g_i2c_open_flag);
    SCI_ASSERT(g_i2c_timeout > 0);
	
    I2C_GetMutex(s_i2c_mutex_ptr);	
    cmd = ((uint32)addr)<<8;
    cmd = cmd | I2CCMD_START | I2CCMD_WRITE ;//send device address
    ptr->cmd = cmd;

    I2C_WAIT_INT
    
    I2C_CLEAR_INT   
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    for(i=0;i<len;i++)
    {
        cmd = ((uint32)pCmd[i])<<8;
        if(i== (len-1))     
            cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command
        else
            cmd = cmd | I2CCMD_WRITE ;

        ptr->cmd = cmd; 

        I2C_WAIT_INT
           
        I2C_CLEAR_INT    

        //check ACK
        if(ack_en)
        {
            I2C_WAIT_ACK
        }

    }
    I2C_PutMutex(s_i2c_mutex_ptr);
    return ERR_I2C_NONE;
}


/*********************************************************************/
//  Description: Write the command array into the slave device 
//  Input:
//      addr     the slave device's address
//      pCmd     the command array's pointer
//      len      the length of the command array
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//        this function is no use stop bit when I2C writes command  
/*********************************************************************/


PUBLIC ERR_I2C_E I2C_WriteCmdArrNoStop(uint8 addr, uint8 *pCmd, uint32 len, BOOLEAN ack_en)
{
    volatile uint32 timetick = 0; 
    volatile uint32 i = 0;
    volatile uint32 cmd = 0;
    volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
    uint32   ret_value = ERR_I2C_NONE;
    
    SCI_ASSERT(NULL != pCmd);
    SCI_ASSERT(g_i2c_open_flag);
    SCI_ASSERT(g_i2c_timeout > 0);

    I2C_GetMutex(s_i2c_mutex_ptr);	
    cmd = ((uint32)addr)<<8;
    cmd = cmd | I2CCMD_START | I2CCMD_WRITE ;//send device address
    ptr->cmd = cmd; 

    I2C_WAIT_INT
    
    I2C_CLEAR_INT   
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    for(i=0;i<len;i++)
    {
        cmd = ((uint32)pCmd[i])<<8;
        if(i== (len-1))     
            cmd = cmd | I2CCMD_WRITE ;//send command
        else
            cmd = cmd | I2CCMD_WRITE ;

        ptr->cmd = cmd; 

        I2C_WAIT_INT
           
        I2C_CLEAR_INT    

        //check ACK
        if(ack_en)
        {
            I2C_WAIT_ACK
        }

    }
    I2C_PutMutex(s_i2c_mutex_ptr);
    return ERR_I2C_NONE;
}


/*********************************************************************/
//  Description: Read a command array from the slave device 
//  Input:
//      addr     the slave device's address
//      pCmd     the command array's pointer
//      len      the length of command array
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_ReadCmdArr(uint8 addr, uint8 *pCmd, uint32 len,BOOLEAN ack_en )
{
    volatile uint32 timetick = 0; 
    volatile uint32 i = 0;
    volatile uint32 cmd = 0;
    volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
    uint32   ret_value = ERR_I2C_NONE;
    
    SCI_ASSERT(NULL !=pCmd );
    SCI_ASSERT(g_i2c_open_flag);
    SCI_ASSERT(g_i2c_timeout > 0);
	
    I2C_GetMutex(s_i2c_mutex_ptr);	
    cmd = ((uint32)(addr|I2C_READ_BIT))<<8;
    cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
    ptr->cmd = cmd; 

    I2C_WAIT_INT
           
    I2C_CLEAR_INT
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    for(i=0;i<len;i++)
    {
        if(i<len-1)
            cmd = I2CCMD_READ;  // I2CCMD_READ|I2CCMD_TX_ACK;
        else
            cmd = I2CCMD_READ|I2CCMD_STOP|I2CCMD_TX_ACK;

        ptr->cmd = cmd;

        I2C_WAIT_INT
                   
        I2C_CLEAR_INT   

        pCmd[i] = (uint8)((ptr->cmd)>>8);
    }
    I2C_PutMutex(s_i2c_mutex_ptr);
    return ERR_I2C_NONE;
}

/*********************************************************************/
//  Description: Write the command array into the slave device 
//  Input:
//      addr     the slave device's address
//      pCmd     the command array's pointer
//      len      the length of the command array
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_WriteCmd_exec(uint8 addr,uint8 sub_addr,uint8 data)
{
       uint16 cmd;
       volatile I2C_CTL_REG_T *i2c_reg_ptr = (I2C_CTL_REG_T *)I2C_BASE;
	   
	I2C_GetMutex(s_i2c_mutex_ptr);	
       
       i2c_reg_ptr->ctl|=BIT_5;
       
       cmd=((uint16)addr<<8)|I2C_CMD_START | I2C_CMD_WRITE;
       
       i2c_reg_ptr->cmd_buf=cmd;
       
       cmd=((uint16)sub_addr<<8)| I2C_CMD_WRITE;

       i2c_reg_ptr->cmd_buf=cmd;
       
       cmd=((uint16)data<<8)|I2C_CMD_WRITE|I2C_CMD_STOP;
       
       i2c_reg_ptr->cmd_buf=cmd;
       
       i2c_reg_ptr->ctl|=BIT_6;
              
       cmd = i2c_reg_ptr->cmd_buf;   
       cmd = i2c_reg_ptr->cmd_buf;            
       cmd = i2c_reg_ptr->cmd_buf;  
	I2C_PutMutex(s_i2c_mutex_ptr);
	return ERR_I2C_NONE;
}

/*********************************************************************/
//  Description: Read a command array from the slave device 
//  Input:
//      addr     the slave device's address
//      pCmd     the command array's pointer
//      len      the length of command array
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC uint8 I2C_ReadCmd_exec(uint8 addr1,uint8 addr2,uint8 sub_addr)
{
       uint16 cmd;
       uint8 ret_val;
       uint32 timeout;
       
       volatile I2C_CTL_REG_T *i2c_reg_ptr = (I2C_CTL_REG_T *)I2C_BASE;
	I2C_GetMutex(s_i2c_mutex_ptr);	
	
       i2c_reg_ptr->ctl|=BIT_5;
      
       cmd=((uint16)addr1<<8)|I2C_CMD_START | I2C_CMD_WRITE;
       
       i2c_reg_ptr->cmd_buf=cmd;
       
       cmd=((uint16)sub_addr<<8)| I2C_CMD_WRITE|I2C_CMD_STOP;

       i2c_reg_ptr->cmd_buf=cmd;
     
       cmd=((uint16)addr2<<8)|I2C_CMD_START | I2C_CMD_WRITE;
       
       i2c_reg_ptr->cmd_buf=cmd;
      
       cmd=((uint16)0x00)|I2C_CMD_READ|I2C_CMD_STOP|I2C_CMD_TX_ACK;
       
       i2c_reg_ptr->cmd_buf=cmd;

       i2c_reg_ptr->ctl|=BIT_6;
       
       timeout=0xFFF;//prevent from the ugly dead loop
       while(!(I2C_CMD_ICLR & (i2c_reg_ptr->ctl)) && timeout--);

       timeout=0xFFF;//prevent from the ugly dead loop
       while( I2C_CMD_BUSY & (i2c_reg_ptr->cmd) && timeout--);
       
       ret_val=(i2c_reg_ptr->cmd)>>8;
       cmd = i2c_reg_ptr->cmd_buf;   
       cmd = i2c_reg_ptr->cmd_buf;            
       cmd = i2c_reg_ptr->cmd_buf; 
       cmd = i2c_reg_ptr->cmd_buf;
	I2C_PutMutex(s_i2c_mutex_ptr);
       return ret_val;   
}
//////////////////////////////////////////
/////////////////for beken
/////////////////////////////////////////
/*********************************************************************/
//  Description: Write the command array into the slave device 
//  Input:
//      addr     the slave device's address
//      pCmd     the command array's pointer
//      len      the length of the command array
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_WriteCmdArr_BK1080(uint8 addr, uint8 reg_addr, uint8 *pCmd, uint32 len, BOOLEAN ack_en)
{
    volatile uint32 timetick = 0; 
    volatile uint32 i = 0;
    volatile uint32 cmd = 0;
    volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
    uint32   ret_value = ERR_I2C_NONE;
    
    SCI_ASSERT(NULL != pCmd);
    SCI_ASSERT(g_i2c_open_flag);
    SCI_ASSERT(g_i2c_timeout > 0);
	
    I2C_GetMutex(s_i2c_mutex_ptr);	
    cmd = ((uint32)addr)<<8;
    cmd = cmd | I2CCMD_START | I2CCMD_WRITE ;//send device address
    ptr->cmd = cmd;

    I2C_WAIT_INT
    
    I2C_CLEAR_INT   
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    cmd = ((uint32)reg_addr)<<9;
    cmd = cmd | I2CCMD_WRITE ;//send device address
    ptr->cmd = cmd;

    I2C_WAIT_INT
    
    I2C_CLEAR_INT   
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }
	
    for(i=0;i<len;i++)
    {
        cmd = ((uint32)pCmd[i])<<8;
        if(i== (len-1))     
            cmd = cmd | I2CCMD_WRITE | I2CCMD_STOP;//send command
        else
            cmd = cmd | I2CCMD_WRITE ;

        ptr->cmd = cmd; 

        I2C_WAIT_INT
           
        I2C_CLEAR_INT    

        //check ACK
        if(ack_en)
        {
            I2C_WAIT_ACK
        }

    }
    I2C_PutMutex(s_i2c_mutex_ptr);
    return ERR_I2C_NONE;
}

/*********************************************************************/
//  Description: Read a command array from the slave device 
//  Input:
//      addr     the slave device's address
//      pCmd     the command array's pointer
//      len      the length of command array
//        ack_en     Enable/Disable check the slave device rsp ACK
//  Return:
//      ERR_I2C_NONE    successfully
//    Note: 
//      None       
/*********************************************************************/
PUBLIC ERR_I2C_E I2C_ReadCmdArr_BK1080(uint8 addr, uint8 reg_addr, uint8 *pCmd, uint32 len,BOOLEAN ack_en )
{
    volatile uint32 timetick = 0; 
    volatile uint32 i = 0;
    volatile uint32 cmd = 0;
    volatile I2C_CTL_REG_T * ptr = (volatile I2C_CTL_REG_T *)I2C_BASE;
    uint32   ret_value = ERR_I2C_NONE;
    
    SCI_ASSERT(NULL !=pCmd );
    SCI_ASSERT(g_i2c_open_flag);
    SCI_ASSERT(g_i2c_timeout > 0);
	
    I2C_GetMutex(s_i2c_mutex_ptr);	
    cmd = ((uint32)addr)<<8;
    cmd = cmd | I2CCMD_START | I2CCMD_WRITE;//send device address
    ptr->cmd = cmd; 

    I2C_WAIT_INT
           
    I2C_CLEAR_INT
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    cmd = ((uint32)((reg_addr<<1)|I2C_READ_BIT))<<8;
    cmd = cmd |I2CCMD_WRITE;//send reg address
    ptr->cmd = cmd; 

    I2C_WAIT_INT
           
    I2C_CLEAR_INT
    
    //check ACK
    if(ack_en)
    {
        I2C_WAIT_ACK
    }

    for(i=0;i<len;i++)
    {
        if(i<len-1)
            cmd = I2CCMD_READ;  // I2CCMD_READ|I2CCMD_TX_ACK;
        else
            cmd = I2CCMD_READ|I2CCMD_STOP|I2CCMD_TX_ACK;

        ptr->cmd = cmd;

        I2C_WAIT_INT
                   
        I2C_CLEAR_INT   

        pCmd[i] = (uint8)((ptr->cmd)>>8);
    }
    I2C_PutMutex(s_i2c_mutex_ptr);
    return ERR_I2C_NONE;
}
///////////////////////////////////
////////////////Beken code end
///////////////////////////////////

/**---------------------------------------------------------------------------*
 **                         Compiler Flag                                     *
 **---------------------------------------------------------------------------*/


#ifdef   __cplusplus
    } 
#endif

/*  End Of File */
